package com.ky.serialport.service;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.ky.myserialport.R;
import com.ky.serialport.socket.event.ConnectBreakEvent;
import com.ky.serialport.socket.event.ConnectFaileEvent;
import com.ky.serialport.socket.event.ConnectSuccessEvent;
import com.ky.serialport.socket.event.ReconnectFaileEvent;
import com.ky.serialport.socket.event.ReconnectSuccessEvent;
import com.ky.serialport.socket.event.SendOrderEvent;
import com.ky.serialport.socket.event.SendResultEvent;
import com.ky.serialport.socket.event.ReadDataEvent;
import com.ky.serialport.socket.listener.OnControlListener;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
 * socket 解析
 */
public class SocketService extends Service {

    private String TAG = this.getClass().getName() + "123456";
    private MyBinder myBinder = new MyBinder();
    private NotificationManager notificationManager;
    private String IP = "127.0.0.1";
    private int port = 8080;
    private String serviceName = "变频电机";
    private String serviceContent = "正在读取数据";
    private byte[] readBuffer = new byte[500]; // 缓存数组
    private byte[] cacheBuffer = new byte[1024 * 8]; //用于存储已经接收的全部数据

    private volatile Socket socket;
    private OutputStream os;
    private InputStream is;
    private Thread myReadThread;

    private  boolean isFirstClear = true;
    private  boolean isConnectThread = true;
    private  boolean isReadThreadLive = true;
    private  boolean isHeardThreadLive = true;

    private  boolean isConnected = false; //连接状态
    private  boolean isOpenHeart = true; //开启心跳


    private int sendHeartTime = 5000; //发送心跳的间隔
    private int reconnectTime = 2000; //重连间隔
    private int successConnectCount = 0; // 连接成功的次数
    private int failConnectCount = 0; //连接失败的次数
    private int breakConnectCount = 0;  //断开连接的次数
    private OnControlListener onControlListener;
    private Notification notification;
    private Notification.Builder builder;

    //EventBus
    private ConnectSuccessEvent connectSuccessEvent = new ConnectSuccessEvent();
    private ConnectFaileEvent connectFaileEvent = new ConnectFaileEvent();

    private ConnectBreakEvent connectBreakEvent = new ConnectBreakEvent();

    private ReconnectFaileEvent reconnectFaileEvent = new ReconnectFaileEvent();
    private ReconnectSuccessEvent reconnectSuccessEvent = new ReconnectSuccessEvent();

    private ReadDataEvent readDataEvent = new ReadDataEvent();
    private SendResultEvent sendResultEvent = new SendResultEvent();

    public SocketService() {

    }

    @Override
    public void onCreate() {
        super.onCreate();
        EventBus.getDefault().register(this);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        start(intent);
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        start(intent);
        return myBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    public class MyBinder extends Binder {

        public SocketService getSocketService() {
            return SocketService.this;
        }

        public void setOnControlListener(OnControlListener onControlListener) {
            SocketService.this.onControlListener = onControlListener;
        }

        public void send(byte[] buffer) {
            SocketService.this.send(buffer);
        }
    }

    private void start(Intent intent) {
        IP = intent.getStringExtra("IP");
        port = intent.getIntExtra("PORT", 4000);
        connectSever();

        // 注册通知服务
        notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        //获取一个Notification构造器
        builder = new Notification.Builder(this.getApplicationContext());
        builder.setLargeIcon(BitmapFactory.decodeResource(this.getResources(), R.mipmap.danpianji)) // 设置下拉列表中的图标(大图标)
                .setContentTitle("变频电机") // 设置下拉列表里的标题
                .setSmallIcon(R.mipmap.danpianji) // 设置状态栏内的小图标
                .setContentText("") // 设置上下文内容
                .setWhen(System.currentTimeMillis()) // 设置该通知发生的时间
                .setVibrate(null)
                .setVibrate(new long[]{0l})
                .setSound(null)
                .setLights(0, 0, 0)
                .setDefaults(NotificationCompat.FLAG_ONLY_ALERT_ONCE);
        // 获取构建好的Notification
        notification = builder.build();
        notification.defaults = Notification.FLAG_ONLY_ALERT_ONCE; /*设置为默认的声音*/
        startForeground(110, notification);
    }

    /**
     * 开启连接
     */
    public void connectSever() {
        connect();
        openHeart(isOpenHeart);
        read();
    }

    /**
     * 发送数据给服务端
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.ASYNC)
    public void sendMsg(SendOrderEvent event) {
        send(event.getSendBuffers());
    }

    /**
     * 连接服务
     *
     * @return
     */
    private void connect() {
        Thread connectThread = new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "run: 连接线程启动" + isConnectThread);
                while (isConnectThread) {
                    while (!isConnected && isConnectThread) {
                        try {
                            socket = null;
                            socket = new Socket(IP, port);
                            socket.setKeepAlive(true);
                            socket.isConnected();
                            os = socket.getOutputStream();
                            is = socket.getInputStream();
                            isConnected = true;
                            successConnectCount += 1;
                            Log.d(TAG, Thread.currentThread().getName());
                            //清空数据缓存
                            while (isFirstClear) {
                                Log.d(TAG, "run: 清空数据缓存");
                                isFirstClear = false;
                                int size = is.read(readBuffer);
                                if (size == -1)
                                    break;
                            }

                            EventBus.getDefault().post(successConnectCount == 1 ? connectSuccessEvent : reconnectSuccessEvent);
                            if (onControlListener != null) {
                                if (successConnectCount == 1) {
                                    onControlListener.onConnectSuccess();
                                } else {
                                    onControlListener.onReconnectSuccess(successConnectCount);
                                }
                            }
                            //设置重连间隔
                            Thread.sleep(reconnectTime);
                        } catch (IOException e) {
                            e.printStackTrace();

                            //设置重连间隔
                            try {
                                Thread.sleep(reconnectTime);
                                failConnectCount += 1;
                                EventBus.getDefault().post(failConnectCount == 1 ? connectFaileEvent : reconnectFaileEvent);

                                if (onControlListener != null) {
                                    if (failConnectCount == 1) {
                                        onControlListener.onConnectFail(e);
                                    } else {
                                        onControlListener.onReconnectFail(failConnectCount);
                                    }
                                }
                            } catch (InterruptedException e1) {
                                e1.printStackTrace();
                            }

                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        connectThread.setName("建立Socket连接线程：" + System.currentTimeMillis());
        connectThread.start();
    }

    /**
     * 发送字节数组
     *
     * @param bytes
     */
    public void send(byte[] bytes) {
        if (isConnected) {
            try {
                os.write(bytes);

                if (bytes.length != 1) {
                    EventBus.getDefault().post(sendResultEvent.setStatus(true));
                    if (onControlListener != null) {
                        onControlListener.onSend(true, bytes);
                    }
                }

            } catch (IOException e) {
                e.printStackTrace();

                if (bytes.length != 1) {
                    if (onControlListener != null) {
                        onControlListener.onSend(false, bytes);
                    }
                    EventBus.getDefault().post(sendResultEvent.setStatus(false));
                }

                socket = null;
                is = null;
                os = null;

                //连接断开
                breakConnectCount += 1;
                if (isConnected) {
                    //暂时认为如果发送失败，就是断开连接（存在不合理性）
                    isConnected = false;
                    if (onControlListener != null) {
                        onControlListener.onConnectBreak(breakConnectCount);
                    }
                    EventBus.getDefault().post(connectBreakEvent);
                }

            }
        } else {
            if (bytes.length != 1) {
                if (onControlListener != null) {
                    onControlListener.onSend(false, bytes);
                }
                EventBus.getDefault().post(sendResultEvent.setStatus(false));
            }
        }

    }

    /**
     * 开启心跳
     *
     * @param boo
     */
    public void openHeart(boolean boo) {
        if (!boo) return;
        final Thread heartThread = new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "run: 心跳线程启动" + isHeardThreadLive);
                while (isHeardThreadLive) {
                    Log.d(TAG, "isHeardThreadLive " + isHeardThreadLive + " === "+ Thread.currentThread().getName());

                    if (isConnected && socket != null) {
                        byte[] bytes = new byte[1];
                        send(bytes);
                    }

                    try {
                        Thread.sleep(sendHeartTime);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        heartThread.setName("心跳线程" + System.currentTimeMillis());

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                heartThread.start();
            }
        },2000);

    }

    /**
     * 启动读取线程;
     */
    private void read() {
        if (myReadThread == null) {
            myReadThread = new Thread(new MyReadRunnable());
            myReadThread.setName("读取线程" + System.currentTimeMillis());
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    myReadThread.start();
                }
            }, 1000);
        }
    }

    /**
     * 读取线程
     */
    private class MyReadRunnable implements Runnable {
        @Override
        public void run() {
            Log.d(TAG, "run: 读取数据线程启动" + isReadThreadLive);
            while (isReadThreadLive) {
                try {
                    Thread.sleep(200);
                    if (socket != null && isConnected) {
                        int contentLen = 0;
                        while (isConnected) {
                            Log.d(TAG, Thread.currentThread().getName());
                            int size = is.read(readBuffer);
                            if (size > 3) {
                                if (readBuffer[0] == 0x01 && readBuffer[1] == 0x03 && readBuffer[2] == 0x38) {
                                    contentLen = 0;
                                    System.arraycopy(readBuffer, 0, cacheBuffer, contentLen, size);
                                    contentLen = size;
                                } else {
                                    System.arraycopy(readBuffer, 0, cacheBuffer, contentLen, size);
                                    contentLen += size;
                                }

                                //根据包的长度发送数据
                                while(contentLen >= 6461){
                                    if (cacheBuffer[0] == 0x01 && cacheBuffer[1] == 0x03 && cacheBuffer[2] == 0x38){
                                        byte[] finalBytes = java.util.Arrays.copyOf(cacheBuffer, contentLen);
                                        EventBus.getDefault().post(readDataEvent.setBytes(finalBytes));
                                        if (onControlListener != null) {
                                            onControlListener.onRead(finalBytes);
                                        }
                                        //校验通过移除整条数据包
                                        System.arraycopy(cacheBuffer, 6461, cacheBuffer, 0, contentLen - 6461);
                                        contentLen-= 6461;
                                    }else {
                                        //移除第一位
                                        System.arraycopy(cacheBuffer, 1, cacheBuffer, 0, contentLen - 1);
                                        contentLen-= 1;
                                    }
                                }

                            }
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void onDestroy() {
        isConnected = false;
        isReadThreadLive = false;
        isConnectThread = false;
        isHeardThreadLive = false;

        try {
            if (socket != null && !socket.isClosed()) {
                socket.close();
                socket = null;
                is = null;
                os = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        stopForeground(true);// 停止前台服务--参数：表示是否移除之前的通知
        notificationManager.cancel(110);
        EventBus.getDefault().unregister(this);
        super.onDestroy();
    }

}
